package helpers;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.util.Collections;

import javax.cache.Cache;
import javax.cache.CacheException;
import javax.cache.CacheManager;
import javax.servlet.ServletException;

import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.blobstore.BlobstoreServiceFactory;
import com.google.appengine.api.files.AppEngineFile;
import com.google.appengine.api.files.FileReadChannel;
import com.google.appengine.api.files.FileService;
import com.google.appengine.api.files.FileServiceFactory;
import com.google.appengine.api.files.FileWriteChannel;
import com.google.appengine.api.images.ImagesService;
import com.google.appengine.api.images.ImagesServiceFactory;
import com.google.appengine.api.urlfetch.FetchOptions;
import com.google.appengine.api.urlfetch.HTTPHeader;
import com.google.appengine.api.urlfetch.HTTPMethod;
import com.google.appengine.api.urlfetch.HTTPRequest;
import com.google.appengine.api.urlfetch.HTTPResponse;
import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.appengine.api.urlfetch.URLFetchServiceFactory;
import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;

import entities.Domain;

public class FileHelper {
	
	public static Domain getDomainByFileName(String filename) throws IOException
	{
		Cache cache=null;
    	try {
		    cache = CacheManager.getInstance().getCacheFactory().createCache(Collections.emptyMap());
		} catch (CacheException e1) {
		   e1.printStackTrace();
		}
		
		
		if(cache!=null&&cache.containsKey(filename))
		{
			return (Domain) cache.get (filename)	;
		}
		else
		{
			
			String key = DataStoreHelper.getKeyFileName(filename);
			if(key==null)
			{
				return null;
			}
			FileService fileService = FileServiceFactory.getFileService();
			
			AppEngineFile file=fileService.getBlobFile(new BlobKey(key));
			FileReadChannel readChannel = fileService.openReadChannel(file, false);
			ObjectInputStream ooi = new ObjectInputStream(Channels.newInputStream(readChannel));
			Domain domain=null;
			try {
				domain = (Domain)ooi.readObject();
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if(cache!=null)
			{
				cache.put(filename, domain);
			}
			return domain;
		}
		
	}
	public static Domain getDomainByKey(String key) throws ClassNotFoundException, IOException
	{
		Cache cache=null;
    	try {
		    cache = CacheManager.getInstance().getCacheFactory().createCache(Collections.emptyMap());
		} catch (CacheException e1) {
		   e1.printStackTrace();
		}
		
		if(cache!=null&&cache.containsKey(key))
		{
			return (Domain) cache.get(key)	;
		}
		else
		{
			
			FileService fileService = FileServiceFactory.getFileService();
			
			AppEngineFile file=fileService.getBlobFile(new BlobKey(key));
			FileReadChannel readChannel = fileService.openReadChannel(file, false);
			ObjectInputStream ooi = new ObjectInputStream(Channels.newInputStream(readChannel));
			Domain domain = (Domain) ooi.readObject();
			if(cache!=null)
			{
				cache.put(key, domain);
			}
			return domain;
		}
		
	}
	
	public static String saveToObject(Domain domain) {
		FileService fileService = FileServiceFactory.getFileService();
		
		AppEngineFile file;
		try {
			file = fileService.createNewBlobFile("text/html", domain.getDomain());
			
			
		FileWriteChannel writeChannel = fileService
				.openWriteChannel(file, true);
	

		ObjectOutputStream oos = new ObjectOutputStream(
				Channels.newOutputStream(writeChannel));
		oos.writeObject(domain);
		oos.flush();
		oos.close();
		// Now finalize
		writeChannel.closeFinally();
		
		Cache cache=null;
    	try {
		    cache = CacheManager.getInstance().getCacheFactory().createCache(Collections.emptyMap());
		} catch (CacheException e1) {
		   e1.printStackTrace();
		}
		String cachePrefix="datastore_";
		String key = fileService.getBlobKey(file).getKeyString();
		if(cache!=null)
		{
			cache.put(domain.getDomain(), domain);
			cache.put(cachePrefix+domain.getDomain(), key);
		}
		return key;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
		
	}
	
	public static String saveToFile(byte[] img, String mineType, String filename) {
		FileService fileService = FileServiceFactory.getFileService();
		
		AppEngineFile file;
		try {
			file = fileService.createNewBlobFile(mineType, filename);
			
			FileWriteChannel writeChannel = fileService
					.openWriteChannel(file, true);
			
			writeChannel.write(ByteBuffer.wrap
		            (img));
			
			// Now finalize
			writeChannel.closeFinally();
			
			Cache cache=null;
	    	try {
			    cache = CacheManager.getInstance().getCacheFactory().createCache(Collections.emptyMap());
			} catch (CacheException e1) {
			   e1.printStackTrace();
			}
			String cachePrefix="datastore_";
			String key = fileService.getBlobKey(file).getKeyString();

			return key;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
		
	}
	
	public static String saveImageToFile(String urlString) throws IOException, ServletException {
		String key = null;
		
		byte[] img = null;
		URLFetchService fetchService =
            URLFetchServiceFactory.getURLFetchService();
		// Fetch the image at the location given by the url query string parameter
		URL url = new URL(urlString);
		// Fetch the image at the location given by the url query string parameter
		FetchOptions fetchOptions =FetchOptions.Builder.withDefaults();
		fetchOptions.setDeadline((double)30*60);
		HTTPRequest req = new HTTPRequest(url, HTTPMethod.GET, fetchOptions);
        HTTPResponse fetchResponse = fetchService.fetch(req);
        
        String fetchResponseContentType = null;
        for (HTTPHeader header : fetchResponse.getHeaders()) {
            // For each request header, check whether the name equals
            // "Content-Type"; if so, store the value of this header
            // in a member variable
            if (header.getName().equalsIgnoreCase("content-type")) {
                fetchResponseContentType = header.getValue();
                break;
            }
        }
        if (fetchResponseContentType != null) {
        	img = (byte[]) fetchResponse.getContent();
        	
        	
        	key = FileHelper.saveToFile(img, fetchResponseContentType, "image.png");
        	
        	/*BlobKey blobKey = new BlobKey(key);
			BlobstoreService blobStoreService = BlobstoreServiceFactory.getBlobstoreService();
			ImagesService imagesService = ImagesServiceFactory.getImagesService();
			System.out.println(imagesService.getServingUrl(blobKey));*/
			
        	
        }
		
		
		return key;
	}
}
